package com.ayu.shortlink.settlement.idempotent;

import com.alibaba.fastjson2.JSON;
import com.ayu.shortlink.settlement.common.biz.user.UserContext;
import com.ayu.shortlink.settlement.common.convention.exception.ClientException;
import lombok.RequiredArgsConstructor;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.redisson.api.RLock;
import org.redisson.api.RedissonClient;
import org.springframework.util.DigestUtils;

/**
 * 幂等消费AOP
 */
@Aspect
@RequiredArgsConstructor
public class IdempotentConsumeAspect {
    private final RedissonClient redissonClient;

    @Around("@annotation(idempotentConsume)")
    public Object handle(ProceedingJoinPoint proceedingJoinPoint, IdempotentConsume idempotentConsume) throws Throwable {
        //获取标识
        String mark = idempotentConsume.Mark();

        String key = String.format("IdempotentConsumeAspect-%s mark:%s:md5:%s", UserContext.getUserId(),mark, calcArgsMd5(proceedingJoinPoint));

        RLock lock = redissonClient.getLock(key);

        if(!lock.tryLock()){
            throw new ClientException(idempotentConsume.message());
        }

        //储存执行结果
        Object result;
        try {
            result = proceedingJoinPoint.proceed();
        }finally {
            lock.unlock();
        }
        return result;
    }

    /**
     * 计算参数的 MD5 值
     */
    private String calcArgsMd5(ProceedingJoinPoint proceedingJoinPoint){
        return DigestUtils.md5DigestAsHex(JSON.toJSONBytes(proceedingJoinPoint.getArgs()));
    }
}
